﻿#include "Connection/UDPConnection/UDPSender.h"
#include "SocketSubsystem.h"
#include "Common/UdpSocketBuilder.h"
#include "Serialization/ArrayWriter.h"


AUDPSender::AUDPSender()
{
	PrimaryActorTick.bCanEverTick = false;
	ShowOnScreenDebugMessages = true;
	IsUDP = true;
}

void AUDPSender::BeginPlay()
{
	Super::BeginPlay();
	StartUDPSender(FString("YourChosenSocketName"), FString("127.0.0.1"), 8888);
}


void AUDPSender::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	if (SenderSocket)
	{
		SenderSocket->Close();
		ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
	}
}

bool AUDPSender::SendMessageTo(const uint8* Data, int32 Count, int32& BytesSent, const FInternetAddr& Destination)
{
	if (!SenderSocket || !OnBeforeSender(Data, Count, Destination)) return false;
	return SenderSocket->SendTo(Data, Count, BytesSent, Destination);
}

bool AUDPSender::StartUDPSender(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool UDP)
{
	// Create Remote Address.
	RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();

	bool bIsValid;
	RemoteAddr->SetIp(*TheIP, bIsValid);
	RemoteAddr->SetPort(ThePort);

	if (!bIsValid)
	{
		ScreenMsg("Rama UDP Sender>> IP address was not valid!", TheIP);
		return false;
	}

	SenderSocket = FUdpSocketBuilder(*YourChosenSocketName).AsReusable().WithBroadcast();

	// check(SenderSocket->GetSocketType() == SOCKTYPE_Datagram);

	// Set Send Buffer Size
	int32 SendSize = 2 * 1024 * 1024;
	SenderSocket->SetSendBufferSize(SendSize, SendSize);
	SenderSocket->SetReceiveBufferSize(SendSize, SendSize);

	// UE_LOG(LogTemp, Log, TEXT("\n\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
	// UE_LOG(LogTemp, Log, TEXT("Rama ****UDP**** Sender Initialized Successfully!!!"));
	// UE_LOG(LogTemp, Log, TEXT("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\n"));

	return true;
}

bool AUDPSender::OnBeforeSender(const uint8* Data, int32 Count, const FInternetAddr& Destination)
{
	return true;
}

bool AUDPSender::UDPSendString(FString ToSend)
{
	if (!SenderSocket)
	{
		ScreenMsg("No sender socket");
		return false;
	}

	int32 BytesSent = 0;

	FAnyCustomData NewData;
	NewData.Scale = FMath::FRandRange(0.0, 1000.0);
	NewData.Count = FMath::RandRange(0.0, 100.0);
	NewData.Color = FLinearColor(FMath::FRandRange(0.0, 1.0), FMath::FRandRange(0.0, 1.0), FMath::FRandRange(0.0, 1.0), 1);

	FArrayWriter Writer;

	Writer << NewData;

	SendMessageTo(Writer.GetData(), Writer.Num(), BytesSent, *RemoteAddr);

	if (BytesSent <= 0)
	{
		const FString Str = "Socket is valid but the receiver received 0 bytes, make sure it is listening properly!";
		// UE_LOG(LogTemp, Error, TEXT("%s"), *Str);
		ScreenMsg(Str);
		return false;
	}

	ScreenMsg("UDP~ Send Succcess! Bytes Sent = ", BytesSent);

	return true;
}
